package services

import (
	"errors"
	"github.com/gin-gonic/gin"
	"github.com/silenceper/wechat/v2/officialaccount/oauth"
	"gorm.io/gorm"
	"server/global"
	model2 "server/internal/model"
	"server/utils/jwts"
	"server/utils/tools"
	"strconv"
	"time"
)

var Login = new(login)

type login struct{}

func (a login) Login(c *gin.Context, data model2.User) (model2.User, int, error) {

	Db := global.GL_DB
	var Expires int
	users := model2.User{}
	res := Db.Model(&users).Where("username = ?", data.Username).First(&users)
	if res.RowsAffected == 0 {
		return users, Expires, errors.New("用户不存在")
	}

	if !tools.ComparePasswords(data.Password, users.Password) {
		return users, Expires, errors.New("密码错误")
	}
	users.LastLoginIp = c.ClientIP()
	users.LastLoginTime = int(time.Now().Unix())
	Db.Model(&users).Updates(&users)

	//创建token
	tokenStr, ExpiresAt, err := jwts.Encrypt(users.ID, data.Username, users.LastLoginIp, 72)
	refreshToken, _, err := jwts.Encrypt(users.ID, data.Username, users.LastLoginIp, 12)

	userToken := model2.UserToken{}
	Db.Model(&userToken).Where("user_id=?", users.ID).First(&userToken)
	userToken.Token = tokenStr
	userToken.ExpiresAt = int(ExpiresAt.Unix())
	userToken.RefreshToken = refreshToken
	if userToken.UserId == 0 {
		userToken.UserId = users.ID
		userToken.Type = "admin"
		Db.Create(&userToken)
	} else {
		Db.Where("user_id=?", users.ID).Updates(userToken)
	}

	if err != nil {
		//log.Println("token 创建失败:", err)
		return users, Expires, err
	}

	users.Token = tokenStr
	Expires = int(ExpiresAt.Unix())
	return users, Expires, nil
}

func (a login) RefreshToken(c *gin.Context, data model2.User) (model2.User, int, error) {

	Db := global.GL_DB
	var Expires int
	users := model2.User{}
	res := Db.Model(&users).Where("username = ?", data.Username).First(&users)
	if res.RowsAffected == 0 {
		return users, Expires, errors.New("用户不存在")
	}

	users.LastLoginIp = c.ClientIP()
	users.LastLoginTime = int(time.Now().Unix())
	Db.Model(&users).Updates(&users)

	//创建token
	tokenStr, ExpiresAt, err := jwts.Encrypt(users.ID, data.Username, users.LastLoginIp, 3)
	refreshToken, _, err := jwts.Encrypt(users.ID, data.Username, users.LastLoginIp, 12)

	userToken := model2.UserToken{}
	Db.Model(&userToken).Where("user_id=?", users.ID).First(&userToken)
	userToken.Token = tokenStr
	userToken.ExpiresAt = int(ExpiresAt.Unix())
	userToken.RefreshToken = refreshToken
	if userToken.UserId == 0 {
		userToken.UserId = users.ID
		userToken.Type = "admin"
		Db.Create(&userToken)
	} else {
		Db.Where("user_id=?", users.ID).Updates(userToken)
	}

	if err != nil {
		//log.Println("token 创建失败:", err)
		return users, Expires, err
	}

	users.Token = tokenStr

	Expires = int(ExpiresAt.Unix())
	return users, Expires, nil
}

// AuthLogin 微信授权登录
func (a login) AuthLogin(c *gin.Context, info oauth.UserInfo) (model2.User, int, error) {

	Db := global.GL_DB
	var Expires int
	users := model2.User{}
	Db.Model(&users).Where("openid = ?", info.OpenID).First(&users)
	err := Db.Transaction(func(tx *gorm.DB) error {
		users.Avatar = info.HeadImgURL
		users.Nickname = tools.UnicodeEmojiCode(info.Nickname)
		users.LastLoginIp = c.ClientIP()
		users.LastLoginTime = int(time.Now().Unix())
		if users.ID == 0 {
			users.Status = "1"
			users.IsAdmin = "0"
			users.Gender = "0"
			users.Openid = info.OpenID
			users.Username = strconv.Itoa(int(time.Now().Unix())) + strconv.Itoa(tools.Rand(10000, 99999))
			if err := tx.Create(&users).Error; err != nil {
				return err
			}
		} else {
			if err := tx.Model(&users).Updates(&users).Error; err != nil {
				return err
			}
		}

		//创建token
		tokenStr, ExpiresAt, _ := jwts.Encrypt(users.ID, users.Username, users.LastLoginIp, 72)
		refreshToken, _, _ := jwts.Encrypt(users.ID, users.Username, users.LastLoginIp, 12)

		userToken := model2.UserToken{}
		Db.Model(&userToken).Where("user_id=?", users.ID).First(&userToken)
		userToken.Token = tokenStr
		userToken.ExpiresAt = int(ExpiresAt.Unix())
		userToken.RefreshToken = refreshToken
		if userToken.UserId == 0 {
			userToken.UserId = users.ID
			userToken.Type = "user"

			if err := tx.Create(&userToken).Error; err != nil {
				return err
			}
		} else {
			if err := tx.Where("user_id=?", users.ID).Updates(userToken).Error; err != nil {
				return err
			}
		}
		users.Token = tokenStr
		Expires = int(ExpiresAt.Unix())
		// 返回 nil 提交事务
		return nil
	})

	return users, Expires, err
}
